#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
截图工具
类似 Windows Snipping Tool (Win+Shift+S)
功能：全屏截图、窗口截图、自定义区域截图
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from PIL import Image, ImageGrab, ImageTk, ImageDraw
import os
import sys
from datetime import datetime

# 导入ttkbootstrap美化
try:
    import ttkbootstrap as ttk
    from ttkbootstrap.constants import *
    from ttkbootstrap.style import Style
    from ttkbootstrap.icons import Icon
    BOOTSTRAP_AVAILABLE = True
except ImportError:
    BOOTSTRAP_AVAILABLE = False

# 导入配置（自动配置Python路径）
from settings import BASE_DIR
from utils.window_utils import calculate_window_size, center_window


class CaptureToolWindow:
    """截图工具窗口"""
    
    def __init__(self, parent=None):
        """初始化窗口"""
        # 创建独立窗口
        if parent:
            if BOOTSTRAP_AVAILABLE:
                self.window = tk.Toplevel(parent)
                # 尝试获取父窗口的样式
                if hasattr(parent, 'style'):
                    self.style = parent.style
                else:
                    self.style = Style(theme='cosmo')
            else:
                self.window = tk.Toplevel(parent)
        else:
            if BOOTSTRAP_AVAILABLE:
                self.style = Style(theme='cosmo')
                self.window = self.style.master
            else:
                self.window = tk.Tk()
        
        if BOOTSTRAP_AVAILABLE:
            self.window.title("截图工具")
        else:
            self.window.title("截图工具")
        
        # 根据屏幕分辨率自适应窗口大小
        width, height = calculate_window_size(
            width_percent=0.3,
            height_percent=0.6,
            min_width=450,
            max_width=600,
            min_height=600,
            max_height=800
        )
        
        # 居中显示窗口
        center_window(self.window, width, height)
        
        self.window.resizable(True, True)
        self.window.minsize(450, 600)
        
        # 截图保存目录
        self.capture_dir = os.path.join(BASE_DIR, "captures")
        os.makedirs(self.capture_dir, exist_ok=True)
        
        # 创建界面
        self.create_widgets()
    
    def create_widgets(self):
        """创建界面组件"""
        # 主框架
        main_frame = tk.Frame(self.window, bg='#f0f0f0')
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # 标题
        title_label = tk.Label(
            main_frame,
            text="截图工具",
            font=("微软雅黑", 18, "bold"),
            bg='#f0f0f0',
            fg='#333'
        )
        title_label.pack(pady=(0, 10))
        
        # 说明文本框
        info_frame = tk.LabelFrame(
            main_frame,
            text="使用说明",
            font=("微软雅黑", 11, "bold"),
            bg='#f0f0f0',
            fg='#555'
        )
        info_frame.pack(fill=tk.X, expand=False, pady=(0, 20))
        
        info_text = """
【操作说明】
• 全屏截图：截取整个屏幕
• 矩形截图：鼠标拖动选择区域
• 窗口截图：选择窗口进行截图

【使用步骤】
1. 点击下方对应的截图按钮
2. 矩形模式：拖动鼠标选择区域
3. 窗口模式：从列表选择窗口
4. 按 ESC 可取消截图

【保存位置】
captures/screenshot_年月日_时分秒.png
        """
        
        info_label = tk.Label(
            info_frame,
            text=info_text,
            font=("微软雅黑", 9),
            justify=tk.LEFT,
            bg='#ffffff',
            fg='#666',
            anchor=tk.NW,
            padx=15,
            pady=10
        )
        info_label.pack(fill=tk.X, expand=False, padx=5, pady=5)
        
        # 按钮区域
        button_frame = tk.Frame(main_frame, bg='#f0f0f0')
        button_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 全屏截图按钮
        fullscreen_btn = tk.Button(
            button_frame,
            text="全屏截图",
            command=self.capture_fullscreen,
            font=("微软雅黑", 12, "bold"),
            bg='#2196F3',
            fg='white',
            width=15,
            height=2,
            cursor='hand2',
            relief=tk.FLAT
        )
        fullscreen_btn.pack(pady=5)
        
        # 矩形截图按钮
        rectangle_btn = tk.Button(
            button_frame,
            text="矩形截图",
            command=self.capture_rectangle,
            font=("微软雅黑", 12, "bold"),
            bg='#4CAF50',
            fg='white',
            width=15,
            height=2,
            cursor='hand2',
            relief=tk.FLAT
        )
        rectangle_btn.pack(pady=5)
        
        # 窗口截图按钮
        window_btn = tk.Button(
            button_frame,
            text="窗口截图",
            command=self.capture_window,
            font=("微软雅黑", 12, "bold"),
            bg='#FF9800',
            fg='white',
            width=15,
            height=2,
            cursor='hand2',
            relief=tk.FLAT
        )
        window_btn.pack(pady=5)
        
        # 分隔线
        separator = ttk.Separator(main_frame, orient='horizontal')
        separator.pack(fill=tk.X, pady=15)
        
        # 底部信息
        info_bottom_frame = tk.Frame(main_frame, bg='#f0f0f0')
        info_bottom_frame.pack(fill=tk.X)
        
        # 保存路径
        path_label = tk.Label(
            info_bottom_frame,
            text=f"保存位置: {self.capture_dir}",
            font=("微软雅黑", 9),
            bg='#f0f0f0',
            fg='#666'
        )
        path_label.pack(pady=5)
        
        # 打开文件夹按钮
        open_folder_btn = tk.Button(
            info_bottom_frame,
            text="打开保存文件夹",
            command=self.open_capture_folder,
            font=("微软雅黑", 10),
            bg='#9C27B0',
            fg='white',
            cursor='hand2',
            relief=tk.FLAT,
            padx=15,
            pady=5
        )
        open_folder_btn.pack(pady=5)
    
    def generate_filename(self):
        """生成文件名"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        return f"screenshot_{timestamp}.png"
    
    def save_image(self, image):
        """保存图像"""
        try:
            filename = self.generate_filename()
            filepath = os.path.join(self.capture_dir, filename)
            image.save(filepath)
            
            # 显示成功消息
            result = messagebox.askquestion(
                "截图成功",
                f"截图已保存：\n{filename}\n\n是否打开保存文件夹？",
                icon='info'
            )
            
            if result == 'yes':
                self.open_capture_folder()
            
            return True
        except Exception as e:
            messagebox.showerror("错误", f"保存截图失败：{str(e)}")
            return False
    
    def capture_fullscreen(self):
        """全屏截图"""
        try:
            # 最小化窗口
            self.window.iconify()
            self.window.update()
            
            # 等待窗口最小化
            self.window.after(200, self._do_fullscreen_capture)
        except Exception as e:
            messagebox.showerror("错误", f"全屏截图失败：{str(e)}")
            self.window.deiconify()
    
    def _do_fullscreen_capture(self):
        """执行全屏截图"""
        try:
            # 截取屏幕
            screenshot = ImageGrab.grab()
            
            # 恢复窗口
            self.window.deiconify()
            
            # 保存图像
            self.save_image(screenshot)
        except Exception as e:
            self.window.deiconify()
            messagebox.showerror("错误", f"全屏截图失败：{str(e)}")
    
    def capture_rectangle(self):
        """矩形截图"""
        try:
            # 隐藏主窗口
            self.window.withdraw()
            
            # 创建截图覆盖层
            self.create_capture_overlay()
        except Exception as e:
            self.window.deiconify()
            messagebox.showerror("错误", f"矩形截图失败：{str(e)}")
    
    def create_capture_overlay(self):
        """创建截图覆盖层"""
        # 先截取屏幕
        screenshot = ImageGrab.grab()
        
        # 创建全屏覆盖窗口
        overlay = tk.Toplevel(self.window)
        overlay.attributes('-fullscreen', True)
        overlay.attributes('-topmost', True)
        overlay.configure(cursor='crosshair')
        
        # 创建半透明背景
        canvas = tk.Canvas(overlay, highlightthickness=0)
        canvas.pack(fill=tk.BOTH, expand=True)
        
        # 显示屏幕截图（带半透明效果）
        photo = ImageTk.PhotoImage(screenshot)
        canvas.create_image(0, 0, anchor=tk.NW, image=photo)
        canvas.photo = photo  # 保持引用
        
        # 添加半透明遮罩
        canvas.create_rectangle(
            0, 0, overlay.winfo_screenwidth(), overlay.winfo_screenheight(),
            fill='black', stipple='gray50'
        )
        
        # 提示文本
        hint_text = canvas.create_text(
            overlay.winfo_screenwidth() // 2,
            30,
            text="按住鼠标左键并拖动选择区域，按 ESC 取消",
            font=("微软雅黑", 16, "bold"),
            fill='white'
        )
        
        # 记录鼠标位置
        start_x = start_y = 0
        rect_id = None
        
        def on_mouse_down(event):
            nonlocal start_x, start_y
            start_x, start_y = event.x, event.y
        
        def on_mouse_move(event):
            nonlocal rect_id
            if start_x and start_y:
                # 删除旧矩形
                if rect_id:
                    canvas.delete(rect_id)
                
                # 绘制新矩形
                rect_id = canvas.create_rectangle(
                    start_x, start_y, event.x, event.y,
                    outline='red', width=3
                )
        
        def on_mouse_up(event):
            end_x, end_y = event.x, event.y
            
            # 确保坐标顺序正确
            x1, x2 = min(start_x, end_x), max(start_x, end_x)
            y1, y2 = min(start_y, end_y), max(start_y, end_y)
            
            # 关闭覆盖层
            overlay.destroy()
            
            # 检查区域大小
            if x2 - x1 < 10 or y2 - y1 < 10:
                self.window.deiconify()
                messagebox.showwarning("警告", "选择的区域太小，请重试")
                return
            
            # 截取选定区域
            region_screenshot = screenshot.crop((x1, y1, x2, y2))
            
            # 恢复主窗口
            self.window.deiconify()
            
            # 保存图像
            self.save_image(region_screenshot)
        
        def on_escape(event):
            overlay.destroy()
            self.window.deiconify()
        
        # 绑定事件
        canvas.bind('<Button-1>', on_mouse_down)
        canvas.bind('<B1-Motion>', on_mouse_move)
        canvas.bind('<ButtonRelease-1>', on_mouse_up)
        overlay.bind('<Escape>', on_escape)
    
    def capture_window(self):
        """窗口截图"""
        try:
            # 获取所有窗口
            import win32gui
            import win32ui
            import win32con
            
            windows = []
            
            def enum_windows_callback(hwnd, windows):
                if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd):
                    windows.append((hwnd, win32gui.GetWindowText(hwnd)))
            
            win32gui.EnumWindows(enum_windows_callback, windows)
            
            if not windows:
                messagebox.showwarning("警告", "未找到可用窗口")
                return
            
            # 创建窗口选择对话框
            self.show_window_selector(windows)
            
        except ImportError:
            messagebox.showerror("错误", "需要安装 pywin32 库才能使用窗口截图功能")
        except Exception as e:
            messagebox.showerror("错误", f"窗口截图失败：{str(e)}")
    
    def show_window_selector(self, windows):
        """显示窗口选择器"""
        selector = tk.Toplevel(self.window)
        selector.title("选择窗口")
        selector.geometry("500x400")
        selector.transient(self.window)
        selector.grab_set()
        
        # 标题
        title_label = tk.Label(
            selector,
            text="请选择要截图的窗口：",
            font=("微软雅黑", 12, "bold")
        )
        title_label.pack(pady=10)
        
        # 列表框
        frame = tk.Frame(selector)
        frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        scrollbar = tk.Scrollbar(frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        listbox = tk.Listbox(
            frame,
            font=("微软雅黑", 10),
            yscrollcommand=scrollbar.set
        )
        listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.config(command=listbox.yview)
        
        # 添加窗口
        for hwnd, title in windows:
            listbox.insert(tk.END, title)
        
        def on_select():
            selection = listbox.curselection()
            if selection:
                hwnd, title = windows[selection[0]]
                selector.destroy()
                self.capture_specific_window(hwnd, title)
        
        # 按钮
        btn_frame = tk.Frame(selector)
        btn_frame.pack(pady=10)
        
        ok_btn = tk.Button(
            btn_frame,
            text="确定",
            command=on_select,
            font=("微软雅黑", 10),
            bg='#4CAF50',
            fg='white',
            width=10
        )
        ok_btn.pack(side=tk.LEFT, padx=5)
        
        cancel_btn = tk.Button(
            btn_frame,
            text="取消",
            command=selector.destroy,
            font=("微软雅黑", 10),
            bg='#f44336',
            fg='white',
            width=10
        )
        cancel_btn.pack(side=tk.LEFT, padx=5)
        
        # 双击选择
        listbox.bind('<Double-Button-1>', lambda e: on_select())
    
    def capture_specific_window(self, hwnd, title):
        """截取指定窗口"""
        try:
            import win32gui
            import win32ui
            import win32con
            from ctypes import windll
            
            # 最小化主窗口
            self.window.iconify()
            self.window.update()
            self.window.after(100)
            
            # 激活目标窗口
            win32gui.SetForegroundWindow(hwnd)
            self.window.after(300)
            
            # 获取窗口位置
            left, top, right, bottom = win32gui.GetWindowRect(hwnd)
            width = right - left
            height = bottom - top
            
            # 截取窗口
            screenshot = ImageGrab.grab(bbox=(left, top, right, bottom))
            
            # 恢复主窗口
            self.window.deiconify()
            
            # 保存图像
            self.save_image(screenshot)
            
        except Exception as e:
            self.window.deiconify()
            messagebox.showerror("错误", f"截取窗口失败：{str(e)}")
    
    def open_capture_folder(self):
        """打开截图保存文件夹"""
        try:
            os.startfile(self.capture_dir)
        except Exception as e:
            messagebox.showerror("错误", f"打开文件夹失败：{str(e)}")
    
    def show(self):
        """显示窗口"""
        self.window.deiconify()
        self.window.lift()
        self.window.focus_force()


def open_capture_tool(parent=None):
    """打开截图工具（供外部调用）"""
    tool = CaptureToolWindow(parent)
    return tool


def main():
    """主函数（独立运行时使用）"""
    root = tk.Tk()
    tool = CaptureToolWindow(None)
    tool.window = root
    root.mainloop()


if __name__ == "__main__":
    main()

